package com.shanzmoo.platform.manage.api.manager;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.shanzmoo.core.domain.dto.SysMenuSaveDTO;
import com.shanzmoo.core.domain.dto.SysMenuUpdateDTO;
import com.shanzmoo.core.domain.vo.AuthMenuRouterVO;
import com.shanzmoo.core.domain.vo.MenuAuthVO;
import com.shanzmoo.core.domain.vo.MenuTreeVO;
import com.shanzmoo.core.domain.vo.RouterAuthVO;
import com.shanzmoo.db.module.psys.entity.PSysMenuEntity;
import com.shanzmoo.db.module.psys.service.IPSysMenuService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 菜单管理
 *
 * @author： Gzhao 2021/3/28
 */
@Component
@RequiredArgsConstructor
public class SysMenuManager {

    private final IPSysMenuService menuService;

    public AuthMenuRouterVO getAuthListByUserId(Integer useId) {
        List<PSysMenuEntity> allMenuList = menuService.getUserMenuList(useId);

        List<MenuAuthVO> menuList = allMenuList.stream()
                .filter(e -> e.getParentId() == 0 && !e.getPath().equals("index") && !e.getPath().equals("/index") )
                .sorted(Comparator.comparingInt(PSysMenuEntity::getIndex))
                .map(MenuAuthVO::create)
                .collect(Collectors.toList());

        obtainChildren(menuList, allMenuList);

        List<RouterAuthVO> routerList = new ArrayList<>();
        for (PSysMenuEntity menuEntity : allMenuList) {
            if (StrUtil.isNotEmpty(menuEntity.getComponent())
                    && StrUtil.isNotEmpty(menuEntity.getRouterName())
                    && StrUtil.isNotEmpty(menuEntity.getPath())) {

                routerList.add(RouterAuthVO.create(menuEntity));
            }
        }
        return AuthMenuRouterVO.create(menuList, routerList);
    }

    public List<MenuTreeVO> getAllTree() {
        List<PSysMenuEntity> allMenuList = menuService.lambdaQuery()
                .eq(PSysMenuEntity::getDeleted, false)
                .list();

        List<MenuTreeVO> rootList = allMenuList.stream()
                .filter(e -> e.getParentId() == 0)
                .sorted(Comparator.comparingInt(PSysMenuEntity::getIndex))
                .map(MenuTreeVO::create)
                .collect(Collectors.toList());

        obtainChildrenForAll(rootList, allMenuList);

        return rootList;
    }

    private void obtainChildren(List<MenuAuthVO> rootList, List<PSysMenuEntity> allMenuList) {
        for (MenuAuthVO menuAuthVO : rootList) {
            List<MenuAuthVO> children = allMenuList.stream()
                    .filter(e -> e.getParentId() == menuAuthVO.getMenuId())
                    .sorted(Comparator.comparingInt(PSysMenuEntity::getIndex))
                    .map(MenuAuthVO::create)
                    .collect(Collectors.toList());

            if (CollUtil.isNotEmpty(children)) {
                menuAuthVO.setChildren(children);
                obtainChildren(children, allMenuList);
            }
        }
    }

    private void obtainChildrenForAll(List<MenuTreeVO> menuList, List<PSysMenuEntity> allMenuList) {
        for (MenuTreeVO menuTreeVO : menuList) {
            List<MenuTreeVO> children = allMenuList.stream()
                    .filter(e -> e.getParentId() == menuTreeVO.getMenuId())
                    .sorted(Comparator.comparingInt(PSysMenuEntity::getIndex))
                    .map(MenuTreeVO::create)
                    .collect(Collectors.toList());

            if (CollUtil.isNotEmpty(children)) {
                menuTreeVO.setChildren(children);
                obtainChildrenForAll(children, allMenuList);
            }
        }
    }

    public void save(SysMenuSaveDTO saveDto) {
        PSysMenuEntity entity = saveDto.convertP();
        menuService.save(entity);
    }

    public void update(SysMenuUpdateDTO updateDto) {
        PSysMenuEntity entity = updateDto.convertP();
        menuService.updateById(entity);
    }

    public void delete(Integer menuId) {
        List<PSysMenuEntity> list = menuService.lambdaQuery()
                .eq(PSysMenuEntity::getDeleted, false)
                .eq(PSysMenuEntity::getParentId, menuId)
                .list();
        Assert.isTrue(CollUtil.isEmpty(list), "请先删除所有子菜单");
        menuService.removeById(menuId);
    }
}
